home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / macos / uae069b2.src.cpt.hqx / UAE069ß2.SRC.CPT / uae069fl2.src / serial.c < prev    next >
C/C++ Source or Header  |  1997-06-13  |  7KB  |  296 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   *
  4.   *  Serial Line Emulation
  5.   *
  6.   * (c) 1996, 1997 Stefan Reinauer <stepan@matrix.kommune.schokola.de>
  7.   * (c) 1997 Christian Schmitt <schmittc@uni-freiburg.de>
  8.   *
  9.   *  Thanks to Chris Hames <bitey@werple.net.au> for his hints.
  10.   *
  11.   */
  12.  
  13. #include "sysconfig.h"
  14. #include "sysdeps.h"
  15.  
  16. #include "config.h"
  17. #include "options.h"
  18. #include "uae.h"
  19. #include "my_memory.h"
  20. #include "custom.h"
  21. #include "readcpu.h"
  22. #include "newcpu.h"
  23. #include "cia.h"
  24.  
  25. //#define __DOS__
  26.  
  27. #undef POSIX_SERIAL
  28. /* Some more or less good way to determine whether we can safely compile in 
  29.  * the serial stuff. I'm certain it breaks compilation on some systems. */
  30. #if defined HAVE_SYS_TERMIOS_H && defined HAVE_POSIX_OPT_H && defined HAVE_SYS_IOCTL_H && defined HAVE_TCGETATTR
  31. #define POSIX_SERIAL
  32. #endif
  33.  
  34. #ifdef POSIX_SERIAL
  35. #include <termios.h>
  36. #include <unistd.h>
  37. #include <sys/ioctl.h>
  38. #endif
  39.  
  40. #if !defined B300 || !defined B230400
  41. #undef POSIX_SERIAL
  42. #endif
  43.  
  44. #ifndef O_NONBLOCK
  45. #define O_NONBLOCK  0//O_NDELAY
  46. #endif
  47.  
  48. #define SERIALDEBUG 1 /* 0, 1, 2 3 */
  49. #define MODEMTEST   1 /* 0 or 1 */
  50.  
  51. void serial_init(void);
  52. void serial_exit(void);
  53.  
  54. uae_u16 SERDATR(void);
  55. void  SERDATS(void);
  56. void  SERPER(uae_u16 w);
  57. void  SERDAT(uae_u16 w);
  58.  
  59. int waitqueue=0,carrier=0,dsr=0;
  60.  
  61. #ifndef __DOS__
  62. int sd = -1;
  63. #else
  64. FILE *sd = NULL;
  65. #endif
  66.  
  67. #ifdef POSIX_SERIAL
  68.     struct termios tios;
  69. #endif
  70.  
  71. uae_u16 serper=0,serdat;
  72.  
  73. void SERPER(uae_u16 w)
  74. {
  75.     int baud=0,pspeed;
  76.  
  77.     if (!currprefs.use_serial)
  78.     return;
  79. #if defined POSIX_SERIAL
  80.     if (serper == w)  /* don't set baudrate if it's already ok */
  81.         return;
  82.     serper=w;
  83.  
  84.     if (w&0x8000)
  85.         fprintf (stdout, "SERPER: 9bit transmission not implemented\n");
  86.  
  87.     switch (w & 0x7fff)
  88.     {
  89.      /* These values should be calculated by the current 
  90.       * color clock value (NTSC/PAL). But this solution is
  91.       * easy and it works.
  92.       */
  93.  
  94.      case 0x2e9b:
  95.      case 0x2e14: baud=300; pspeed=B300; break;
  96.      case 0x170a:
  97.      case 0x0b85: baud=1200; pspeed=B1200; break;
  98.      case 0x05c2:
  99.      case 0x05b9: baud=2400; pspeed=B2400; break;
  100.      case 0x02e9:
  101.      case 0x02e1: baud=4800; pspeed=B4800; break;
  102.      case 0x0174:
  103.      case 0x0170: baud=9600; pspeed=B9600; break;
  104.      case 0x00b9:
  105.      case 0x00b8: baud=19200; pspeed=B19200; break;
  106.      case 0x005c:
  107.      case 0x005d: baud=38400; pspeed=B38400; break;
  108.      case 0x003d: baud=57600; pspeed=B57600; break;
  109.      case 0x001e: baud=115200; pspeed=B115200; break;
  110.      case 0x000f: baud=230400; pspeed=B230400; break;
  111.      default:
  112.       fprintf(stdout,"SERPER: unsupported baudrate (0x%04x) %d\n",w&0x7fff,
  113.               (unsigned int)(3579546.471/(double)((w&0x7fff)+1)));  return;
  114.     }
  115.  
  116.     if(tcgetattr(sd,&tios)<0) {
  117.       fprintf(stderr,"SERPER: TCGETATTR failed\n");
  118.       return;
  119.     }
  120.  
  121.     if(cfsetispeed(&tios,pspeed)<0) {    /* set serial input speed */
  122.       fprintf(stderr,"SERPER: CFSETISPEED (%d bps) failed\n",baud);
  123.       return;
  124.     }
  125.     if(cfsetospeed(&tios,pspeed)<0) {    /* set serial output speed */
  126.       fprintf(stderr,"SERPER: CFSETOSPEED (%d bps) failed\n",baud);
  127.       return;
  128.     }
  129.  
  130.     if(tcsetattr(sd,TCSADRAIN,&tios)<0) {
  131.       fprintf(stderr,"SERPER: TCSETATTR failed\n");
  132.       return;
  133.     }
  134. #endif
  135.  
  136. #if SERIALDEBUG > 0
  137.     fprintf(stdout,"SERPER: set baudrate to %d bit/sec\n",baud);
  138. #endif
  139. }
  140.  
  141. /* Not (fully) implemented yet:
  142.  *  -  Something's wrong with the Interrupts. 
  143.  *     (NComm works, TERM does not. TERM switches to a
  144.  *     blind mode after a connect and wait's for the end
  145.  *     of an asynchronous read before switching blind
  146.  *     mode off again. It never gets there on UAE :-< )
  147.  *
  148.  *  -  RTS/CTS handshake, this is not really neccessary,
  149.  *     because you can use RTS/CTS "outside" without
  150.  *     passing it through to the emulated Amiga
  151.  *
  152.  *  -  ADCON-Register ($9e write, $10 read) Bit 11 (UARTBRK)
  153.  *     (see "Amiga Intern", pg 246)
  154.  */
  155.  
  156. void SERDAT(uae_u16 w)
  157. {
  158.     unsigned char z;
  159.  
  160.     if (!currprefs.use_serial)
  161.     return;
  162.  
  163.     z=(unsigned char)(w&0xff);
  164.  
  165. #ifndef __DOS__
  166.     if (sd!=0) {
  167.     //write (sd,&z,1);
  168.     }
  169. #else
  170.     if (sd!=NULL) {
  171.     fputc (z, sd);
  172.     fflush (sd);
  173.     }
  174. #endif
  175.  
  176. #if SERIALDEBUG > 2
  177.     fprintf(stderr,"SERDAT: wrote 0x%04x\n",w);
  178. #endif
  179.  
  180.     serdat|=0x2000; /* Set TBE in the SERDATR ... */
  181.     intreq|=1;      /* ... and in INTREQ register */
  182.     return;
  183. }
  184.  
  185. uae_u16 SERDATR(void)
  186. {
  187.     if (!currprefs.use_serial)
  188.     return 0;
  189. #if SERIALDEBUG > 2
  190.     fprintf(stdout,"SERDATR: read 0x%04x\n",serdat);
  191. #endif
  192.     waitqueue = 0;
  193.     return serdat;
  194. }
  195.  
  196. void SERDATS(void)
  197. {
  198.     unsigned char z;
  199.     int status;
  200.  
  201.     if ((!currprefs.use_serial)||((serdat&0x4000)!=0))
  202.         return;
  203.  
  204.     if (waitqueue==1) {
  205.       intreq|=0x0800;
  206.       return;
  207.     }
  208.     if (0) { //((read (sd, &z,1))==1) {
  209.       waitqueue=1;
  210.       serdat=0x4100; /* RBF and STP set! */
  211.       serdat|=((unsigned int)z)&0xff;
  212.       intreq|=0x0800; /* Set RBF flag (Receive Buffer full) */
  213.  
  214. #if SERIALDEBUG > 1
  215.       fprintf (stdout,"SERDATS: received 0x%02x --> serdat==0x%04x\n",
  216.                (unsigned int)z, (unsigned int)serdat);
  217. #endif
  218. #ifdef POSIX_SERIAL
  219.       ioctl(sd, TIOCMGET, &status);
  220.       if (status & TIOCM_CAR) {
  221.         if (!carrier) {
  222.           CIA_shakehands_set(0x20); /* Push up Carrier Detect line */
  223.           fprintf (stdout,"SERDATS: carrier detect.\n");
  224.           carrier=1;
  225.         }
  226.       } else {
  227.         if (carrier) {
  228.           CIA_shakehands_clear(0x20); /* Carrier lost */
  229.           fprintf (stdout,"SERDATS: carrier lost.\n");
  230.           carrier=0;
  231.         }
  232.       }
  233.  
  234.       if (status & TIOCM_DSR) {
  235.         if (!dsr) {
  236.           CIA_shakehands_set(0x08); /* DSR on */
  237.           dsr=1;
  238.         }
  239.       } else {
  240.         if (dsr) {
  241.           CIA_shakehands_clear(0x08); /* DSR off */
  242.           dsr=0;
  243.         }
  244.       }
  245. #endif
  246.     }
  247. }
  248.  
  249. void serial_init(void)
  250. {
  251.     if (!currprefs.use_serial)
  252.     return;
  253.  
  254. #ifndef __DOS__
  255.     if ((sd=open(sername,O_RDWR|O_NONBLOCK))<0)
  256.       fprintf (stderr,"Error: Could not open Device %s\n",sername);
  257. #else
  258.     if ((sd=open(sername,O_RDWR|O_NONBLOCK|O_BINARY))<0)
  259.       fprintf (stdout,"Error: Could not open Device %s\n",sername);
  260. #endif
  261.  
  262. #ifdef POSIX_SERIAL
  263.     if(tcgetattr(sd,&tios)<0) {        /* Initialize Serial tty */
  264.       fprintf(stderr,"Serial: TCGETATTR failed\n");
  265.       return;
  266.     }
  267.  
  268.     cfmakeraw(&tios);
  269.  
  270. #ifndef MODEMTEST
  271.     tios.c_cflag &= ~CRTSCTS; /* Disable RTS/CTS */
  272. #else
  273.     tios.c_cflag |= CRTSCTS; /* Enabled for testing modems */
  274. #endif
  275.  
  276.     if(tcsetattr(sd,TCSADRAIN,&tios)<0) {
  277.       fprintf(stderr,"Serial: TCSETATTR failed\n");
  278.       return;
  279.     }
  280. #endif
  281.     serdat=0x2000;
  282.     return;
  283. }
  284.  
  285. void serial_exit(void)
  286. {
  287. #ifndef __DOS__
  288.     if (sd != 0)
  289.       close(sd);
  290. #else
  291.     if (sd != NULL)
  292.       fclose(sd);
  293. #endif
  294.     return;
  295. }
  296.